/*
 * Copyright (c) 2009 the original author or authors
 *
 * Permission is hereby granted to use, modify, and distribute this file
 * in accordance with the terms of the license agreement accompanying it.
 */

package org.robotlegs.utilities.modular.mvcs
{
	import flash.events.Event;
	import flash.system.ApplicationDomain;
	
	import org.robotlegs.base.CommandMap;
	import org.robotlegs.base.ContextEvent;
    import org.robotlegs.base.StarlingMediatorMap;
    import org.robotlegs.core.ICommandMap;
	import org.robotlegs.core.IInjector;
    import org.robotlegs.core.IStarlingMediatorMap;
    import org.robotlegs.mvcs.StarlingContext;
    import org.robotlegs.utilities.modular.base.StarlingModuleCommandMap;
	import org.robotlegs.utilities.modular.base.StarlingModuleEventDispatcher;
	import org.robotlegs.utilities.modular.core.IStarlingModuleCommandMap;
	import org.robotlegs.utilities.modular.core.IStarlingModuleContext;
	import org.robotlegs.utilities.modular.core.IStarlingModuleEventDispatcher;

    import starling.display.DisplayObjectContainer;

    /**
     * Contains additional mappings and facilitates the use of a parent injector
     * to create a child injector for a module. 
     * @author Joel Hooks
     * 
     */    
    public class StarlingModuleContext extends StarlingContext implements IStarlingModuleContext
    {
        protected var _applicationDomain:ApplicationDomain;
        
        protected var _moduleDispatcher:IStarlingModuleEventDispatcher;

        protected function get moduleDispatcher():IStarlingModuleEventDispatcher
        {
            return _moduleDispatcher;
        }

        protected function set moduleDispatcher(value:IStarlingModuleEventDispatcher):void
        {
            _moduleDispatcher = value;
        }
        
        protected var _moduleCommandMap:IStarlingModuleCommandMap;

        protected function get moduleCommandMap():IStarlingModuleCommandMap
        {
            return _moduleCommandMap || (_moduleCommandMap = new StarlingModuleCommandMap(moduleDispatcher, injector.createChild(_applicationDomain), reflector));
        }
        
        protected function set moduleCommandMap(value:IStarlingModuleCommandMap):void
        {
            _moduleCommandMap = value;
        }
  
        /**
         * The <code>ICommandMap</code> for this <code>IContext</code>
         */
        override protected function get commandMap():ICommandMap
        {
            return _commandMap || (_commandMap = new CommandMap(eventDispatcher, injector.createChild(_applicationDomain), reflector));
        }

   		/**
		 * @private
		 */
		override protected function set commandMap(value:ICommandMap):void
		{
			_commandMap = value;
		}

		/**
		 * @private
		 */
		override protected function set mediatorMap(value:IStarlingMediatorMap):void
		{
			_mediatorMap = value;
		}
        /**
         * The <code>IMediatorMap</code> for this <code>IContext</code>
         */
        override protected function get mediatorMap():IStarlingMediatorMap
        {
            return _mediatorMap || (_mediatorMap = new StarlingMediatorMap(contextView, injector.createChild(_applicationDomain), reflector));
        }
        
        public function StarlingModuleContext(contextView:DisplayObjectContainer=null, autoStartup:Boolean=true, parentInjector:IInjector = null, applicationDomain:ApplicationDomain = null)
        {
            _applicationDomain = applicationDomain || ApplicationDomain.currentDomain;
            if(parentInjector)
            {
                _injector = parentInjector.createChild(_applicationDomain);
            }
            super(contextView, autoStartup);
        }
        
        override protected function mapInjections():void
        {
            super.mapInjections();
            initializeModuleEventDispatcher();
            injector.mapValue(IStarlingModuleCommandMap, moduleCommandMap);
        }
        
        protected function initializeModuleEventDispatcher():void
        {
            if(injector.hasMapping(IStarlingModuleEventDispatcher) )
            {
                moduleDispatcher = injector.getInstance(IStarlingModuleEventDispatcher);
            }
            else
            {
                moduleDispatcher = new StarlingModuleEventDispatcher(this);
                injector.mapValue(IStarlingModuleEventDispatcher, moduleDispatcher);
            }          
        }
        
        protected function dispatchToModules(event:Event):Boolean
        {
            if(moduleDispatcher.hasEventListener(event.type))
                return moduleDispatcher.dispatchEvent(event);
            return true;
        }
        
        public function dispose():void
        {
            dispatchEvent(new ContextEvent(ContextEvent.SHUTDOWN));
            _commandMap.unmapEvents();
            _moduleCommandMap.unmapEvents();
            _moduleCommandMap = null;
            _moduleDispatcher = null;
            _contextView = null;
            _injector = null;
            _reflector = null;
            _commandMap = null;
            _mediatorMap = null;
            _viewMap = null;
            _eventDispatcher = null;
            _applicationDomain = null;
        }
    }
}